	
#include <syslog.h>

#include <stdio.h>
#include <string.h>
#include <pin.h>
#include <aos/kernel.h>
#include <aos/debug.h>
#include <ulog/ulog.h>

#include "audio_process.h"
#include "app_codec.h"
#include "g711.h"

// #include "verify_success.h"
// #include "verify_failed.h"

#define TAG "aprocess"

#define AUDIO_PLAY_BUF_LEN      (16 * 500)      // 16 bit/16000 hz 500 ms
#define CODEC_RECV_BUFF_LEN     (16 * 2 * 400)      // 400 ms audio

#define MIN(a, b)   ((a) < (b) ? (a) : (b))

static int g_audio_record_running = 0;
// static int g_audio_compression_rate = 2;
// static audio_coding_type_e g_audio_coding_type = CODING_TYPE_G711A;

static int16_t g_audio_play_buf[AUDIO_PLAY_BUF_LEN];
static uint8_t g_audio_recv_buf[CODEC_RECV_BUFF_LEN];

#define DUMP_DATA 0

#if DUMP_DATA
uint8_t g_dump_audio_data[1024 * 1024];
int g_dump_audio_data_offset = 0;
uint8_t g_dump_audio_data_raw[1024 * 1024];
int g_dump_audio_data_raw_offset = 0;
static uint8_t test_data[16 * 2 * 1000];
#endif

int app_audio_init()
{
    app_codec_init();
    return 0;
}

int app_audio_record_start()
{
    int ret;

	ret = app_codec_input_start();
    if (ret == 0) {
        g_audio_record_running = 1;
        return 0;
    }

    return -1;
}

int app_audio_record_get(uint8_t *data, int size, uint32_t *time_stamp)
{
    CHECK_PARAM(g_audio_record_running && data && size > 0 && time_stamp, -1);

    // int available_num = codec_cache_available_read(g_codec_cache);
    long long time_stamp_ms;
    int ret;
    int decode_offset = 0;
    uint32_t ts = 0;

    do {
        ret = app_codec_input_read(&time_stamp_ms, g_audio_recv_buf, CODEC_RECV_BUFF_LEN);
        if (ret > 0) {
            if (size > 0 && ret <= (size - decode_offset) * 2) {
                if (!ts) {
                    ts = time_stamp_ms / 1000;
                }

#if DUMP_DATA
                if (ret > 0 && g_dump_audio_data_raw_offset + ret <= 1024 * 1024) {
                    memcpy(g_dump_audio_data_raw + g_dump_audio_data_raw_offset, g_audio_recv_buf, ret);
                    g_dump_audio_data_raw_offset += ret;
                }
#endif

                for (int i = 0; i < ret / 2; i++) {
                    data[decode_offset++] = linear2alaw(*(int16_t *)&g_audio_recv_buf[i * 2]);
                }
                
            } else if (ret > (size - decode_offset) * 2) {
                break;
            }
        }
    } while (ret == 0);

    *time_stamp = ts;
    return decode_offset;
}

int app_audio_record_stop()
{
	app_codec_input_stop();

    g_audio_record_running = 0;
    return 0;
}

int app_audio_play(uint8_t *g711_data, int size, int sample_rate)
{
    CHECK_PARAM(g711_data && size > 0, -1);

    int offset = 0;
    int chunk_size;

    // app_codec_output_start();

    if(sample_rate == 16000) {
        while (offset < size) {
            chunk_size = MIN(size - offset, AUDIO_PLAY_BUF_LEN);

            for (int i = 0; i < chunk_size; i++) {
                g_audio_play_buf[i] = alaw2linear(g711_data[offset + i]);
            }

            app_codec_output_write((const uint8_t *)g_audio_play_buf, chunk_size * 2);
            offset += chunk_size;
        }
    } else if(sample_rate == 8000) {
        while (offset < size) {
            chunk_size = MIN(size - offset, AUDIO_PLAY_BUF_LEN/2);

            for (int i = 0; i < chunk_size; i++) {
                g_audio_play_buf[i * 2] = alaw2linear(g711_data[offset + i]);
                g_audio_play_buf[i * 2 + 1] = g_audio_play_buf[i * 2];
            }

            app_codec_output_write((const uint8_t *)g_audio_play_buf, chunk_size * 4);
            offset += chunk_size;
        }
    }

    // app_codec_output_stop();

    return 0;
}

// #include "audio.h"
int app_audio_record_uint_test()
{
    // uint32_t ts;
    // int ret;

    app_audio_init();

    // while (1) {
    //     printf("start play\n");

    //     // app_codec_output_start();

    //     int write_len = 16 * 20;
    //     unsigned int offset = 0;
    //     while (offset < sizeof(audio_g711a)) {
    //         write_len = MIN(write_len, sizeof(audio_g711a) - offset);
    //         app_audio_play(audio_g711a + offset, write_len, 16000);
    //         // app_codec_output_write(output_pcm + offset, write_len);

    //         offset += write_len;
    //     }

    //     aos_msleep(write_len / 32);
    //     // app_codec_output_stop();
    //     printf("stop play\n");

    //     aos_msleep(2000);
    // }

    // int cnt = 0;
    // while (1) {
    //     app_audio_record_start();


    // #if DUMP_DATA
    //     printf("start %d times record\n", ++cnt);
    //     g_dump_audio_data_offset = 0;

    //     for (int i = 0; i < 100; i++) {
    //         ret = app_audio_record_get(test_data, 16 * 500, &ts);

    //         printf("audio record get size=%d, ts=%u\n", ret, ts);
            
    //         if (ret > 0 && g_dump_audio_data_offset + ret <= 1024 * 1024) {
    //             memcpy(g_dump_audio_data + g_dump_audio_data_offset, test_data, ret);
    //             g_dump_audio_data_offset += ret;
    //         } else {
    //             aos_msleep(100);
    //         }
    //     }
    // #endif

    //     app_audio_record_stop();
    // }
    return 0;
}
